package cn.finder0519.applist;

import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings;
import android.view.ContextMenu;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;

import java.text.Collator;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.Objects;

public class MainActivity extends AppCompatActivity {

    static final String PKG_ANGLE = "com.android.angle";
    static final String PKG_TRACEUR = "com.android.traceur";
    static final String PKG_SETTINGS = "com.android.settings";
    static final String PKG_CONTACTS = "com.android.contacts";
    static final String PKG_CAMERA = "com.android.camera2";
    static final String PKG_GALLERY = "com.android.gallery3d";
    static final String STR_SPACE = " ";

    private SwipeRefreshLayout swipeRefreshLayout;
    List<MyAppInfo> myAppInfoList;
    MyAppListAdapter adapter;
    private String appName;
    private String pkgName;
    private String appVer;
    private String targetSdkVersion;
    private String minSdkVersion;

    private int selectedPosition = -1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        doRefresh();

        ListView listView = findViewById(R.id.list1);
        adapter = new MyAppListAdapter();
        listView.setAdapter(adapter);

        registerForContextMenu(listView);

        listView.setOnItemClickListener((adapterView, view, i, l) -> {
            Intent intent = getPackageManager().getLaunchIntentForPackage(myAppInfoList.get(i).getPkgName());
            if (intent != null) {
                startActivity(intent);
            }
        });

        listView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int i, long id) {
                // 选中某项时执行
                selectedPosition = i;
                appName = myAppInfoList.get(i).getAppName();
                pkgName = myAppInfoList.get(i).getPkgName();
                appVer = myAppInfoList.get(i).getAppVer();
                targetSdkVersion = myAppInfoList.get(i).getTargetSdkVersion();
                minSdkVersion = myAppInfoList.get(i).getMinSdkVersion();
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }

        });

        listView.setOnItemLongClickListener((adapterView, view, i, l) -> {
            appName = myAppInfoList.get(i).getAppName();
            pkgName = myAppInfoList.get(i).getPkgName();
            appVer = myAppInfoList.get(i).getAppVer();
            targetSdkVersion = myAppInfoList.get(i).getTargetSdkVersion();
            minSdkVersion = myAppInfoList.get(i).getMinSdkVersion();
            return false;
        });

        swipeRefreshLayout = findViewById(R.id.swipeRefreshLayout);

        swipeRefreshLayout.setOnRefreshListener(() -> {
            doRefresh();
            adapter.notifyDataSetChanged();
            swipeRefreshLayout.setRefreshing(false);
            Toast.makeText(MainActivity.this, getResources().getString(R.string.number_of_apps, String.valueOf(myAppInfoList.size())), Toast.LENGTH_SHORT).show();
        });

    }

    private List<MyAppInfo> getAvailableApps() throws PackageManager.NameNotFoundException {
        PackageManager packageManager = getPackageManager();
        Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.addCategory(Intent.CATEGORY_LAUNCHER);

        List<ApplicationInfo> installedApps = packageManager.getInstalledApplications(0);

        List<MyAppInfo> myAppInfoList = new ArrayList<>();

        for (ApplicationInfo applicationInfo : installedApps) {
            Intent appLaunchIntent = packageManager.getLaunchIntentForPackage(applicationInfo.packageName);
            if (appLaunchIntent != null && packageManager.resolveActivity(appLaunchIntent, 0) != null) {
                String pkgName = applicationInfo.packageName;
                String appName = packageManager.getApplicationLabel(applicationInfo).toString();
                String appVer = packageManager.getPackageInfo(pkgName, PackageManager.GET_META_DATA).versionName;
                int targetSdkVersionNum = Objects.requireNonNull(packageManager.getPackageInfo(pkgName, PackageManager.GET_META_DATA).applicationInfo).targetSdkVersion;
                String targetSdkVersion = targetSdkVersionNum + STR_SPACE + "(" + getAndroidVerName(targetSdkVersionNum) + ")";
                int minSdkVersionNum = Objects.requireNonNull(packageManager.getPackageInfo(pkgName, PackageManager.GET_META_DATA).applicationInfo).minSdkVersion;
                String minSdkVersion = minSdkVersionNum + STR_SPACE + "(" + getAndroidVerName(minSdkVersionNum) + ")";
                Drawable appIcon = packageManager.getApplicationIcon(applicationInfo);
                if (!pkgName.equals(getPackageName()) && !(pkgName.equals(PKG_ANGLE) || pkgName.equals(PKG_TRACEUR))) {
                    myAppInfoList.add(new MyAppInfo(pkgName, appName, appVer, targetSdkVersion, minSdkVersion, appIcon));
                }
            }
        }

        for (MyAppInfo myAppInfo : myAppInfoList) {
            if (myAppInfo.getPkgName().equals(PKG_SETTINGS)) {
                myAppInfo.setAppName(getResources().getString(R.string.app_name_settings));
            }
            if (myAppInfo.getPkgName().equals(PKG_CONTACTS)) {
                myAppInfo.setAppName(getResources().getString(R.string.app_name_contacts));
            }
            if (myAppInfo.getPkgName().equals(PKG_CAMERA)) {
                myAppInfo.setAppName(getResources().getString(R.string.app_name_camera));
            }
            if (myAppInfo.getPkgName().equals(PKG_GALLERY)) {
                myAppInfo.setAppName(getResources().getString(R.string.app_name_gallery));
            }
        }

        myAppInfoList.sort((o1, o2) -> {
            Comparator<Object> comparator = Collator.getInstance(Locale.CHINA);
            return comparator.compare(o1.getAppName(), o2.getAppName());
        });

        return myAppInfoList;

    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_MENU) {
            if (selectedPosition >= 0) {
                ListView listView = findViewById(R.id.list1);

                int firstVisiblePosition = listView.getFirstVisiblePosition();
                int wantedChild = selectedPosition - firstVisiblePosition;

                if (wantedChild >= 0 && wantedChild < listView.getChildCount()) {
                    View selectedView = listView.getChildAt(wantedChild);
                    openContextMenu(selectedView);
                    return true;
                }
            } else {
                Toast.makeText(this, getResources().getString(R.string.select_an_app), Toast.LENGTH_SHORT).show();
            }
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override
    public void onResume() {
        doRefresh();
        adapter.notifyDataSetChanged();
        super.onResume();
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);
        menu.setHeaderTitle(appName);

        menu.add(Menu.NONE, 1, Menu.NONE, getResources().getString(R.string.version, appVer));
        menu.add(Menu.NONE, 2, Menu.NONE, getResources().getString(R.string.target_sdk_version, targetSdkVersion));
        menu.add(Menu.NONE, 3, Menu.NONE, getResources().getString(R.string.min_sdk_version, minSdkVersion));
        menu.add(Menu.NONE, 4, Menu.NONE, getResources().getString(R.string.copy_to_clipboard));
        menu.add(Menu.NONE, 5, Menu.NONE, getResources().getString(R.string.app_info));
    }

    @Override
    public boolean onContextItemSelected(MenuItem item) {
        if (item.getItemId() == 4) {
            ClipboardManager clipboardManager = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append(appName);
            stringBuilder.append("\n");
            stringBuilder.append(getResources().getString(R.string.package_name, pkgName));
            stringBuilder.append("\n");
            stringBuilder.append(getResources().getString(R.string.version, appVer));
            stringBuilder.append("\n");
            stringBuilder.append(getResources().getString(R.string.target_sdk_version, targetSdkVersion));
            stringBuilder.append("\n");
            stringBuilder.append(getResources().getString(R.string.min_sdk_version, minSdkVersion));
            stringBuilder.append("\n");

            ClipData clipData = ClipData.newPlainText("AppInfo", stringBuilder);
            clipboardManager.setPrimaryClip(clipData);
            Toast.makeText(this, getResources().getString(R.string.copied), Toast.LENGTH_SHORT).show();
        }
        if (item.getItemId() == 5) {
            if (Utils.isTvDevice(this.getApplicationContext())) {
                Toast.makeText(this, getResources().getString(R.string.tv_not_supported), Toast.LENGTH_SHORT).show();
                return true;
            }
            Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
            intent.setData(Uri.fromParts("package", pkgName, null));
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(intent);
            return true;
        }
        return super.onContextItemSelected(item);
    }

    class MyAppListAdapter extends BaseAdapter {

        @Override
        public int getCount() {
            return myAppInfoList.size();
        }

        @Override
        public Object getItem(int i) {
            return myAppInfoList.get(i);
        }

        @Override
        public long getItemId(int i) {
            return i;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder;
            if (convertView == null) {
                convertView = LayoutInflater.from(getApplicationContext()).inflate(R.layout.list_item, parent, false);
                holder = new ViewHolder();
                holder.textView1 = convertView.findViewById(R.id.app_name);
                holder.textView2 = convertView.findViewById(R.id.pkg_name);
                holder.imageView = convertView.findViewById(R.id.app_icon);
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder) convertView.getTag();
            }

            holder.textView1.setText(myAppInfoList.get(position).getAppName());
            holder.textView2.setText(myAppInfoList.get(position).getPkgName());
            holder.imageView.setImageDrawable(myAppInfoList.get(position).getAppIcon());
            return convertView;
        }

        class ViewHolder {
            TextView textView1;
            TextView textView2;
            ImageView imageView;
        }
    }

    private void doRefresh() {
        try {
            myAppInfoList = getAvailableApps();
        } catch (PackageManager.NameNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    private String getAndroidVerName(int verNum) {
        String androidVerName;
        switch (verNum) {
            case 3:
                androidVerName = "Android 1.5";
                break;
            case 4:
                androidVerName = "Android 1.6";
                break;
            case 5:
                androidVerName = "Android 2.0";
                break;
            case 6:
                androidVerName = "Android 2.0.1";
                break;
            case 7:
                androidVerName = "Android 2.1";
                break;
            case 8:
                androidVerName = "Android 2.2";
                break;
            case 9:
                androidVerName = "Android 2.3";
                break;
            case 10:
                androidVerName = "Android 2.3.3";
                break;
            case 11:
                androidVerName = "Android 3.0";
                break;
            case 12:
                androidVerName = "Android 3.1";
                break;
            case 13:
                androidVerName = "Android 3.2";
                break;
            case 14:
                androidVerName = "Android 4.0";
                break;
            case 15:
                androidVerName = "Android 4.0.3";
                break;
            case 16:
                androidVerName = "Android 4.1";
                break;
            case 17:
                androidVerName = "Android 4.2";
                break;
            case 18:
                androidVerName = "Android 4.3";
                break;
            case 19:
                androidVerName = "Android 4.4";
                break;
            case 20:
                androidVerName = "Android 4.4W";
                break;
            case 21:
                androidVerName = "Android 5.0";
                break;
            case 22:
                androidVerName = "Android 5.1";
                break;
            case 23:
                androidVerName = "Android 6.0";
                break;
            case 24:
                androidVerName = "Android 7.0";
                break;
            case 25:
                androidVerName = "Android 7.1";
                break;
            case 26:
                androidVerName = "Android 8.0";
                break;
            case 27:
                androidVerName = "Android 8.1";
                break;
            case 28:
                androidVerName = "Android 9";
                break;
            case 29:
                androidVerName = "Android 10";
                break;
            case 30:
                androidVerName = "Android 11";
                break;
            case 31:
                androidVerName = "Android 12";
                break;
            case 32:
                androidVerName = "Android 12L";
                break;
            case 33:
                androidVerName = "Android 13";
                break;
            case 34:
                androidVerName = "Android 14";
                break;
            case 35:
                androidVerName = "Android 15";
                break;
            case 36:
                androidVerName = "Android 16";
                break;
            default:
                androidVerName = "Unknown";
        }

        return androidVerName;
    }

}